package at.irian.jsfatwork.broker.domain.order;

import at.irian.jsfatwork.broker.domain.DomainModelException;
import at.irian.jsfatwork.broker.domain.client.Client;
import at.irian.jsfatwork.broker.domain.account.Accounting;
import at.irian.jsfatwork.broker.domain.stock.Quote;
import at.irian.jsfatwork.broker.domain.stock.StockExchange;
import at.irian.jsfatwork.broker.domain.stock.Stock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * @author Manfred Geiler
 */
@Component
public class Ordering {

    @Autowired
    private StockExchange stockExchange;

    @Autowired
    private Accounting accounting;


    public Order createNewOrder(Client client, OrderType orderType, Stock stock) {
        return new Order(orderType, OrderStatus.PENDING, stock, null, 0, client);
    }

    

    public void validate(Order order) {
        Quote quote = stockExchange.getQuote(order.getStock());

        BigDecimal amount = quote.getAmount();

        switch (order.getOrderType()) {
            case BUY:
                if (order.getLimit() != null) {
                    if (amount.compareTo(order.getLimit()) > 0) {
                        throw new DomainModelException("Quote (" + amount + ") out of limit " + order.getLimit());
                    }
                }
                accounting.validateBuy(order.getClient(), amount);
                break;
            case SELL:
                if (order.getLimit() != null && order.getLimit().compareTo(amount) > 0) {
                    throw new DomainModelException("Quote (" + amount + ") out of limit " + order.getLimit());
                }
                accounting.validateSell(order.getClient(), order.getStock(), order.getQuantity());
                break;
            default:
                throw new IllegalStateException("unsupported enum (" + order.getOrderType().name() + ")");
        }
    }


    public void sendAndExecuteOrder(Order order) {

        validate(order);

        OrderResponse orderResponse = stockExchange.sendAndExecuteOrder(order);

        order.processOrderResponse(orderResponse);

        if (order.isComplete()) {

            switch (order.getOrderType()) {
                case BUY:
                    accounting.buy(
                            order.getClient(),
                            order.getStock(),
                            order.getQuantity(),
                            order.getCompletionPrice());
                    break;
                case SELL:
                    accounting.sell(order.getClient(),
                            order.getStock(),
                            order.getQuantity(),
                            order.getCompletionPrice());
                    break;
                default:
                    throw new IllegalStateException("unsupported enum (" + order.getOrderType().name() + ")");
            }
        }
    }



}
